home *** CD-ROM | disk | FTP | other *** search
/ Your Choice 3 / Your Choice Software Collection 3.iso / prgmming / swag08 / sound.swg < prev    next >
Text File  |  1994-09-22  |  43KB  |  1 lines

  1. SWAGOLX.EXE (c) 1993 GDSOFT  ALL RIGHTS RESERVED 00010                                                                           1      08-24-9413:31ALL                      JORDAN RITTER            SoundBlaster Detect      SWAG9408    o¿F    19     ■"   {ππPB> It's me again.  I need code to detect a SB/SB Compat.  card.  I haveπPB> code which will detect the port, but I also need a way of detecting theπPB> SB's IRQ and DMA channel.  Is there any such code available?ππThis code was just posted about 2 weeks ago (I believe)... }πππProgram DetectSoundBlaster;ππUses DOS, CRT;ππFunction hex(a : Word; b : Byte) : String;πConst digit : Array[$0..$F] Of Char = '0123456789ABCDEF';πVar i : Byte;π  xstring : String;πBeginπ  xstring:='';π  For i:=1 To b Doπ  Beginπ    Insert(digit[a And $000F], xstring, 1);π    a:=a ShR 4π  End;π  hex:=xstringπEnd; {hex}ππProcedure SoundPort;πVar xbyte1, xbyte2, xbyte3, xbyte4: Byte;π  xword, xword1, xword2, temp, sbport: Word;π  sbfound, portok: Boolean;ππBeginπ  ClrScr;π  Write('Sound Blaster: ');π  sbfound:=False;π  xbyte1:=1;π  While (xbyte1 < 7) And (Not sbfound) Doπ  Beginπ    sbport:=$200 + ($10 * xbyte1);π    xword1:=0;π    portok:=False;π    While (xword1 < $201) And (Not portok) Doπ    Beginπ      If (Port[sbport + $0C] And $80) = 0 Thenπ        portok:=True;π      Inc(xword1)π    End;π    If portok Thenπ    Beginπ      xbyte3:=Port[sbport + $0C];π      Port[sbport + $0C]:=$D3;π      For xword2:=1 To $1000 Do {nothing};π      xbyte4:=Port[sbport + 6];π      Port[sbport + 6]:=1;π      xbyte2:=Port[sbport + 6];π      xbyte2:=Port[sbport + 6];π      xbyte2:=Port[sbport + 6];π      xbyte2:=Port[sbport + 6];π      Port[sbport + 6]:=0;π      xbyte2:=0;π      Repeatπ        xword1:=0;π        portok:=False;π        While (xword1 < $201) And (Not portok) Doπ        Beginπ          If (Port[sbport + $0E] And $80) = $80 Thenπ            portok:=True;π          Inc(xword1)π        End;π        If portok Thenπ          If Port[sbport + $0A] = $AA Thenπ            sbfound:=True;π        Inc(xbyte2);π      Until (xbyte2 = $10) Or (portok);π      If Not portok Thenπ      Beginπ        Port[sbport + $0C]:=xbyte3;π        Port[sbport + 6]:=xbyte4;π      End;π    End;π    If sbfound Thenπ    Beginπ      Write('Yes');π      Write(' Port: ');π      Write('$', Hex(sbport, 3));π    Endπ    Elseπ      Inc(xbyte1);π  End;π  If Not sbfound Thenπ    Write('No');πEnd;{soundport}ππBeginπ  SoundPort;πEnd.ππ                                                                                                         2      08-24-9413:40ALL                      JASON DYER               Fm-voices                SWAG9408    sm    20     ■"   {πCould somebody tell me how to program the FM-voices of my sound-blaster ?ππHere's a .sbi player for you...π}πprogram SBIread;πuses Crt;πconst SBIREG : array[1..11] of Word =π  ($20,$23,$40,$43,$60,$63,$80,$83,$E0,$E3,$C0);πvarπ  FromF: file;π  I: integer;π  FN: string;π  NumRead, NumWritten: Word;π  buf: array[1..2048] of Char;π  ch: char;π  IsSBI: boolean;π  SBIName: string;πprocedure Bit;πbeginπ  Delay(1); {something fancier was suggested, but this works fine}πend;                                                                           ππfunction CheckSoundCard: boolean;πvar Temp, Temp2: byte;πbeginπ  port[$388]:=$4; repeat until Port[$22E] > 127;π  port[$389]:=$60; repeat until Port[$22E] > 127;π  port[$389]:=$80; repeat until Port[$22E] > 127;π  Temp:=port[$388];π  port[$388]:=$2; repeat until Port[$22E] > 127;π  port[$389]:=$FF; repeat until Port[$22E] > 127;π  port[$388]:=$4; repeat until Port[$22E] > 127;π  port[$389]:=$21; repeat until Port[$22E] > 127;π  Delay(1);π  Temp2:=port[$388];π  port[$388]:=$4; repeat until Port[$22E] > 127;π  port[$389]:=$60; repeat until Port[$22E] > 127;π  port[$389]:=$80; repeat until Port[$22E] > 127;π  If ((temp and $E0)=$00) and ((temp2 and $E0)=$c0) thenπ    CheckSoundCard:=True else CheckSoundCard:=False;πend;πprocedure ClearCard;πvar CP: byte;πbeginπ  For CP:=0 to 255 do beginπ    port[$388]:=CP;π    port[$389]:=0;π  end;πend;πprocedure Sounder(A,B: byte);πbeginπ  port[$388]:=A; Bit;π  port[$389]:=B; Bit;πend;πbeginπ  Writeln('SBI file player');π  if not CheckSoundCard then beginπ    writeln('Soundcard not detected!');π    halt(1);π  end;π  FN:=ParamStr(1);π  If Pos('.',FN)=0 then FN:=FN+'.SBI';π  Assign(FromF, FN);π  Reset(FromF, 1);π  BlockRead(FromF,buf,SizeOf(buf),NumRead);π  Close(FromF);π  If (buf[1]='S') and (buf[2]='B') and (buf[3]='I') and (ord(buf[4])=26)π    then IsSBI:=True else IsSBI:=False;π  If IsSBI=False then Writeln('Not a SBI file!') else beginπ    SBIName:='';π    I:=4;π    repeatπ      i:=i+1;π      if (ord(buf[i])<>0) then SBIName:=SBIName+buf[i];π    until ord(buf[i])=0;π    Writeln('Name of file      : ',FN);π    Writeln('Name of instrument: ',SBIName);π    ClearCard;π    for i:=1 to 11 do Sounder(SBIreg[i],ord(buf[i+36]));π    Sounder($A0,$58);π    Sounder($B0,$31);π    Delay(900);π    ClearCard;π  end;πend.π                                                                                                               3      08-24-9413:46ALL                      CHRISTIAN KULLANDER      Max Volume on SB         SWAG9408    ÷L≈┌    9      ■"   {π KP> HOW CAN I CHANGE THE OVERALL VOLUME OF SOUND BLASTER ? It must be aπ KP> single OUT , or something . . .ππActually I did a small program yesterday that maximizes the master, VOC and FMπvolumes... Here it is:ππ[------------------------------ C u t -----------------------]π}ππprogram MaxVol;ππ  beginπ    Port[$224] := 4;     { register 04h - VOC volume }π    Port[$225] := $FF;π    Port[$224] := $22;   { register 22h - *** Master volume *** }π    Port[$225] := $FF;π    Port[$224] := $26;   { register 26h - FM volume }π    Port[$225] := $FF;π  end.ππ{ππThis works fine on the SB16 I'm using, and it should work as well with all theπother SB models.πThe left volume is in one of the nibbles, and the right in the other (I can'tπremember which one is in which nibble though...;).πThe max volume for L/R is 15/15, and since 15 shl 4 or 15 = 255 (0FFh) that'sπthe value I use. I haven't tried but I guess that you can use the 225h port toπread the register contents as well as write it.ππ // Christian Kullanderπ}π     4      08-24-9413:49ALL                      OSCAR WAHLBERG           Sound/NoSound (BASM)     SWAG9408    ;î╧    6      ■"   πUses CRT;ππ  Procedure Sound (Hertz : Word);Assembler;π  Asmπ    Mov  Bx,SPπ    Mov  Bx,&Hertzπ    Mov  Ax,34DDhπ    Mov  Dx,0012hπ    CMP  Dx,Bxπ    JNB  @J1π    Div  Bxπ    Mov  Bx,Axπ    In   Al,61hπ    Test Al,03hπ    JNZ  @J2π    OR   Al,03hπ    OUT  61h,Alπ    Mov  Al,-4Ahπ    OUT  43h,Alπ   @J2:π    Mov  Al,Blπ    OUT  42h,Alπ    Mov  Al,Bhπ    Out  42h,Alπ   @J1:π  End; {Sound}ππ  Procedure NoSound;Assembler;π  Asmπ    IN  AL,61hπ    AND AL,0FChπ    OUT 61h,ALπ  End;ππBeginππ      SOUND (150);π      DELAY (100);π      SOUND (400);π      DELAY (100);π      NOSOUND;πEND.                                                        5      08-25-9409:08ALL                      RODNEY JOHNSON           FM Synth Code            SWAG9408    b╗∙Y    39     ■"   {π  I got FM-synth code for the PAS (originally for the SB).  Here it is:π}πProgram fmtest;πusesπ  sbfm, crt;πconstπ  instrument: TFMInstrument = (SoundCharacteristic: ($11, $1);π                               Level: ($8A, $40);π                               AttackDecay: ($F0, $F0);π                               SustainRelease: ($FF, $B3);π                               WaveSelect: ($01, $00);π                               FeedBack: $00;π                               Filler: ($06, $00, $00, $00, $00, $00));π  notes: array[0..12] of integer = ($157, $16B, $181, $198, $1B0, $1C1, $1E5,π        $202, $220, $241, $263, $287, $2AE);πbeginπ  SbFMReset;π  SbFMSetVoice(0,@instrument);π  SbFMSetVoice(1,@instrument);π  SbFMSetVoice(11,@instrument);π  SbFMSetVoice(12,@instrument);ππ  SbFMKeyOn(0,notes[0],2);π  delay(250);π  SbFMKeyOn(1,notes[4],3);π  delay(250);π  SbFMKeyOn(1,notes[7],3);π  delay(250);π  SbFMKeyOn(1,notes[12],3);π  delay(1000);ππ  sbFMKeyOff(0);π  sbFMKeyOff(1);π  sbFMKeyOff(11);π  sbFMKeyOff(12);π  sbFMReset;πend.ππUnit SbFM;πinterfaceπtypeπ  PFMInstrument = ^TFMInstrument;π  TFMInstrument = recordπ                    SoundCharacteristic:array[0..1] of byte;π                    Level:              array[0..1] of byte;π                    AttackDecay:        array[0..1] of byte;π                    SustainRelease:     array[0..1] of byte;π                    WaveSelect:         array[0..1] of byte;π                    Feedback:           byte;π                    filler:             array[0..5] of byte;π                  end;πconstπ  SbIOAddr=$220;π  LeftFmAddress=0;π  RightFmAddress=2;π  FMADDRESS=$08;πProcedure WriteFM(chip, addr, data: byte);πProcedure SbFmReset;πProcedure SbFMKeyOff(voice: integer);πProcedure SbFMKeyOn(voice, freq, octave: integer);πProcedure SbFMVoiceVolume(voice, vol: integer);πprocedure sbFMSetVoice(voicenum: integer; Ins: PFMInstrument);πimplementationπProcedure WriteFM(chip, addr, data: byte);πvarπ  ChipAddr:                                integer;π  t:                                        byte;πbeginπ  if chip>0 then chipaddr:=SbIOAddr + RightFMAddress elseπ               chipaddr:=sbIOAddr + LeftFMAddress;π  chipaddr:=SbIOAddr + FMAddress;π  asmπ    push dxπ    push axπ    push cxπ    mov dx,chipaddrπ    mov al,addrπ    out dx,alπ    in al,dxπ    inc dxπ    mov al,dataπ    out dx,alπ    dec dxπ    mov cx,4π@L:π    in al,dxπ    loop @Lπ    pop cxπ    pop axπ    pop dxπ  end;πend;πProcedure SbFmReset;πBeginπ  WriteFM(0, 1, 0);π  WriteFM(1, 1, 0);πend;πProcedure SbFMKeyOff(voice: integer);πvarπ  regnum:                                byte;π  chip:                                        integer;πbeginπ  chip:=voice div 11;π  regnum:=$B0 + (voice mod 11);π  WriteFM(chip, regnum, 0);πend;πProcedure SbFMKeyOn(voice, freq, octave: integer);πvarπ  regnum, t:                                byte;π  chip:                                        integer;πbeginπ  chip:=voice div 11;π  regnum:=$A0 + (voice mod 11);π  WriteFM(chip, regnum, freq and $FF);π  regnum:=$B0 + (voice mod 11);π  t:=(freq shr 8) or (octave shl 2) or $20;π  WriteFM(chip, regnum, t);πend;πProcedure SbFMVoiceVolume(voice, vol: integer);πvarπ  regnum:                                byte;π  chip:                                        integer;πbeginπ  chip:=voice div 11;π  regnum:=$40 + (voice mod 11);π  WriteFM(chip, regnum, vol);πend;πprocedure sbFMSetVoice(voicenum: integer; Ins: PFMInstrument);πvarπ  opcellnum:                                byte;π  celloffset, i, chip:                        integer;πbeginπ  chip:=voicenum div 11;π  voicenum:=voicenum mod 11;π  celloffset:=(voicenum mod 3) + ((voicenum div 3) shr 3);π  opcellnum:=$20 + celloffset;π  WriteFM(chip, opcellnum, ins^.SoundCharacteristic[0]);π  inc(opcellnum, 3);π  WriteFM(chip, opcellnum, ins^.SoundCharacteristic[1]);π  opcellnum:=$40 + celloffset;π  WriteFM(chip, opcellnum, ins^.level[0]);π  inc(opcellnum, 3);π  WriteFM(chip, opcellnum, ins^.Level[1]);π  opcellnum:=$60 + celloffset;π  WriteFM(chip, opcellnum, ins^.AttackDecay[0]);π  inc(opcellnum, 3);π  WriteFM(chip, opcellnum, ins^.AttackDecay[1]);π  opcellnum:=$80 + celloffset;π  WriteFM(chip, opcellnum, ins^.SustainRelease[0]);π  inc(opcellnum, 3);π  WriteFM(chip, opcellnum, ins^.SustainRelease[1]);π  opcellnum:=$E0 + celloffset;π  WriteFM(chip, opcellnum, ins^.WaveSelect[0]);π  inc(opcellnum, 3);π  WriteFM(chip, opcellnum, ins^.WaveSelect[1]);π  opcellnum:=$C0 + voicenum;π  WriteFM(chip, opcellnum, ins^.feedback);πend;πend.ππ{πMessage 1 is FMTEST.PASπMessages 2+3 are SBFM.PASπThat's all.  One thing: if you can make this work with more than twoπvoices at a time, I'd be interested in improved code.  I think that thisπcode uses the AdLib compatibility, which is by no means impressive :-).π}π                                                                         6      08-25-9409:11ALL                      JURI PAKASTE             S3M header               SWAG9408    J8«~    47     ■"   {πFrom: jurip@clinet.fi (Juri Pakaste)ππHopefully someone here has experience reading S3M headers...πI'm trying to read the S3M header. I get the name right, I thinkπI get the number of instruments right, but I can't get the numberπof patterns right. If I understand correctly the file which comesπwith Scream Tracker 3.01 (see below), the number of patternsπshould be located in bytes 35-36 (why on earth two bytes? Whoπwould use over 255 patterns?). The numbers I get have nothing toπdo with numbers DMP and Inertia Player give, though. My little test-πprogram, S3MREAD.EXE, tells me, for example, that a module that hasπ55 (I think) patterns, has in fact 99. Just great. Some of the valuesπit gives manage to get pretty near the ones DMP and IPlay give,πbut... you get the idea.ππHere is there relevant part of S3M technical documentation:ππ------------------------------------8<----------------------------------π π                                Song/Module headerπ          0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   Fπ        -----------------------------------------------------------------π  0000: | Song name, max 28 chars (incl. NUL)                           |π        |---------------------------------------------------------------|π  0010: |                                               |1Ah|Typ| x | x |π        |---------------------------------------------------------------|π  0020: |OrdNum |InsNum |PatNum | Flags | Cwt/v |  Ffv  |'S'|'C'|'R'|'M'|π        |---------------------------------------------------------------|π  0030: |m.v|i.s|i.t|m.m| x | x | x | x | x | x | x | x | x | x | x | x |π        |---------------------------------------------------------------|π  0040: |Channel settings for 32 channels, 255=unused,+128=disabled     |π        |---------------------------------------------------------------|π  0050: |                                                               |π        |---------------------------------------------------------------|π  0060: |Orders; length=OrdNum (must be even)                           |π        |---------------------------------------------------------------|π  xxxx: |Parapointers to instruments; length=InsNum*2                   |π        |---------------------------------------------------------------|π  xxxx: |Parapointers to patterns; length=PatNum*2                      |π        -----------------------------------------------------------------ππ π        Typ     = File type: 16=module,17=songπ        Ordnum  = Number of orders in fileπ        Insnum  = Number of instruments in fileπ        Patnum  = Number of patterns in fileπ        Cwt/v   = Created with tracker / version: &0xfff=version, >>12=trackerπ                        ST30:0x1300π        Ffv     = File format version;π                        1=originalπ                        2=original BUT samples unsignedπ        Parapointers are OFFSET/16 relative to the beginning of the header.π π        PLAYING AFFECTORS / INITIALIZERS:π        Flags   =  +1:st2vibrato π                   +2:st2tempoπ                   +4:amigaslidesπ                   +8:0vol optimizationsπ                   +16:amiga limitsπ                   +32:enable filter/sfxπ        m.v     = master volumeπ        m.m     = master multiplier (&15) + stereo(=+16)π        i.s     = initial speed (command A)π        i.t     = initial tempo (command T)π π        Channel types:π        &128=on, &127=type: (127=unused)π        8  - L-Adlib-Melody 1 (A1)      0  - L-Sample 1 (S1)π        9  - L-Adlib-Melody 2 (A2)      1  - L-Sample 2 (S2)π        10 - L-Adlib-Melody 3 (A3)      2  - L-Sample 3 (S3)π        11 - L-Adlib-Melody 4 (A4)      3  - L-Sample 4 (S4)π        12 - L-Adlib-Melody 5 (A5)      4  - R-Sample 5 (S5)π        13 - L-Adlib-Melody 6 (A6)      5  - R-Sample 6 (S6)π        14 - L-Adlib-Melody 7 (A7)      6  - R-Sample 7 (S7)π        15 - L-Adlib-Melody 8 (A8)      7  - R-Sample 8 (S8)π        16 - L-Adlib-Melody 9 (A9)π                                        26 - L-Adlib-Bassdrum (AB)π        17 - R-Adlib-Melody 1 (B1)      27 - L-Adlib-Snare    (AS)π        18 - R-Adlib-Melody 2 (B2)      28 - L-Adlib-Tom      (AT)π        19 - R-Adlib-Melody 3 (B3)      29 - L-Adlib-Cymbal   (AC)π        20 - R-Adlib-Melody 4 (B4)      30 - L-Adlib-Hihat    (AH)π        21 - R-Adlib-Melody 5 (B5)      31 - R-Adlib-Bassdrum (BB)π        22 - R-Adlib-Melody 6 (B6)      32 - R-Adlib-Snare    (BS)π        23 - R-Adlib-Melody 7 (B7)      33 - R-Adlib-Tom      (BT)π        24 - R-Adlib-Melody 8 (B8)      34 - R-Adlib-Cymbal   (BC)π        25 - R-Adlib-Melody 9 (B9)      35 - R-Adlib-Hihat    (BH)ππSo, shouldn't this piece of code be able to read the name,πnumber of instruments and number of patterns right:ππ}πProgram S3MReader;πVarπ   NameArray       :       Array [1..28] Of Char;π   InstrArray, PatArray : Array [1..2] Of Byte;π   InstrByte, PatByte   :       Byte;π   f : File;π   i       :       Integer;π   j       :       Integer;π   S3MName :       String;ππBeginπ   WriteLn;π   WriteLn;π   If ParamCount = 1 Thenπ   Beginπ      Assign(f,ParamStr(1));π      Reset(f,1);π      BlockRead(f,NameArray,28,i);π      For j := 1 To 28 Do S3MName := S3MName + NameArray[j];π      j := 28;π      While (Ord(S3MName[Length(S3MName)]) = 0) Or (Ord(S3MNameπ   (continues...)[Length(S3MName)]) = 32) Doπ      Beginπ         j := j - 1;π         S3MName[0] := Chr(j);π      End;π      Seek(f,33);π      BlockRead(f,InstrArray,2,i);π      InstrByte := InstrArray[1] + InstrArray[2];π      BlockRead(f,PatArray,2,i);π      PatByte := PatArray[1] + PatArray[2];π      WriteLn('Name: ',S3MName);π      WriteLn('Number of instruments: ',InstrByte);π      WriteLn('Number of patterns: ',PatByte);π      Close(f);π   End;πEnd.ππ                                                                                                                    7      08-25-9409:11ALL                      ADRIAN DENOON            PROGRAMMING SB AND FM    SWAG9408    └┴ë    43     ■"   {πAs I promised, here is the other reply that I am sending you containing theπinformation on Programming the SB via CT-VOICE.DRV.ππBefore I begin, This message may be a little long, so if for any reason, youπloose the end of it or sumthin', let me know, and I'll repost it split upπinto sections, but right now I'll just make one long message.ππO.K. Here we go...πThe information supplied will concern playback and recording of digitalπsamples on the SB's digital channel(s) using the driver supplied byπCreative Labs, CT-VOICE.DRV.ππThere should be a lot of information available on BBS's if you look for itπand want to follow up anything, but for the meaan time, this informationπis taken from a book called "The Sound Blaster Book" by Axel Stolz,πpublished by Abacus ISBN 1-55755-164-2.ππLet me first correct myself about the comment that the driver is executedπas an interrupt... Similar, but not quite... You don't actually make andπinterrupt call (i.e: INT n), but rather make the actual call to the addressπthat the driver was loaded into (i.e: CALL n).ππThe first thing you need to do is load the driver into memory.  Note, theπsegment may be anywhere (you store the pointer as a reference), but theπoffset MUST be zero.  The loading is done as follows...π1.) Allocate memory and get pointer to the block.π2.) Load the driver from disk into the allocated space.πNote: I am not going into much detail regarding error checking, but youπshould do checking on things such as allocation being ok and not NULL, andπsee whether the file exists on the disk, and whether or not it is a validπdriver (this can be done by checking to see that the letters "CT" areπcontained in bytes 3 and 4).ππThe code is as follows (in Pascal):π(Please forgive any minor discrepencies, as I am not a Pascal programmer,π but a C programmer, and I'm only trying to extract those sections that seemπ inportant, so I may not know which functions are Pascal's and which areπ user defined, but you should get the general idea. )π}πVARπ   F : File;π   PtrToDrv : Pointer;ππBEGINπ   Assign( F, 'CT-VOICE.DRV' );π   Reset( F, 1 );π   AllocateMem( PtrToDrv, FileSize(F) );π   Blockread( F, PtrToDrv^, FileSize(F) );π   Close( F );πEND;π{πNOTE: The varible PtrToDrv should be global, as you will be needing it toπreference the memory at a later stage.ππNow that you have the driver loaded, you can start to make function callsπto it.  This is done by setting the register BX to the number of theπfunction that you want to execute, and various other memory registers toπthe parameters, and then calling the address stored in the "PtrToDrv"πvarible.  Return values are usually stored in the register AX.ππEXAMPLE: Function 6: Play a sample:π-------- Input registers:  BX = Function numberπ                           ES:DI = Pointer to sampleπ         Return registers: None.π}πPROCEDURE PlaySample( BufferAddr : Pointer );πVARπ   VSeg, VOfs : WORD;πBEGINπ   VSeg := Seg( BufferAddr^ );π   VOfs := Ofs( BufferAddr^ );π   ASMπ      MOV   BX, 6π      MOV   ES, VSegπ      MOV   Di, VOfsπ      CALL  PtrToDrvπ   END;πEND;ππ{πThe following are a list of all the function available from the CT-VOICE.DRVπdriver.  Note, you will call them by setting BX = function number, settingπthe other registers, and then executing "CALL PtrToDrv":ππ----------------------------------------------------------------------------π#: Description:                  Parameters:π-- -------------------------     -------------------------------------------π0  Determain driver version      AH=Main number (on return)π                                 AL=Sub number (on return)ππ1  Set port address              AX=Port addressππ2  Set interrupt                 AX=Interrupt numberππ3  Initialize driver             AX=0 Successfull (on return)π                                 AX=1 SB not found (on return)π                                 AX=2 Port address error (on return)π                                 AX=3 Interrupt error (on return)ππ4  Loudspeaker on/off            AL=0 offπ                                 AL=1 onππ5  Set "StatusWord" address      ES:DI=Status addressπ                                 (The WORD varible at this address will storeπ                                  the status of the playback so that you canπ                                  monitor the playback of the sample.)ππ6  Sample playback               ES:DI=Sample addressππ7  Record sample                 AX=Sampling rateπ                                 DX:CX=Lengthπ                                 ES:DI=Sample addressππ8  Abort sample                  noneππ9  De-Install driver             noneπ                              π10 Pause Sample                  AX=0 Successfull (on return)π                                 AX=1 Not successfull (on return)ππ11 Continue sample               AX=0 Successfull (on return)π                                 AX=1 Not successfull (on return)ππ12 Interrupt loop                AX=0 At end of loopπ                                 AX=1 Immediatelyπ                                 AX=0 Successfull (on return)π                                 AX=1 No loop being executedππ13 User defined driver function  DX:AX=Function addressπ                                 ES:BX=Address of the current data blockπ}π                                                                                                 8      08-25-9409:11ALL                      GREG VIGNEAULT           SoundBlaster version...  SWAG9408    ∙│ï    17     ■"   {π Someone in an Assembly conference posted a routine to determine theπ version of a Sound Blaster card. I've adapted it for use in TP ...π}ππPROGRAM sb;               { Determine Sound Blaster version.  TP5+  }π                          { Jul.13.94 Greg Vigneault                }πUSES  Dos,                { import GetEnv                           }π      Crt;                { import Delay                            }πVAR Major, Minor : BYTE;  { version has major & minor parts         }ππ(*-----------------------------------------------------------------*)π{ this procedure returns 0.0 if any error condition...              }πPROCEDURE SBver (VAR Maj, Min : BYTE);π  VAR bev : STRING[32];                       { environment string  }π      j,k : WORD;                             { scratch variables   }π  BEGINπ    Maj := 0;  Min := 0;                      { initialize          }π    bev := GetEnv('BLASTER');                 { look in environment }π    IF bev[0] = #0 THEN EXIT;                 { no sign of Blaster  }π    j := Pos('A',bev);                        { search for i/o port }π    IF j = 0 THEN EXIT ELSE INC(j);           { none?               }π    Val( '$'+Copy(bev,j,3), j, k );           { base port number    }π    IF k <> 0 THEN EXIT;                      { if bad port value   }π    INC(j,$C);                                { command port        }π    Port[j] := $E1;                           { command             }π    DEC(j,2);                                 { input port          }π    Delay(20);                                { wait for response   }π    Maj := Port[j];                           { version major part  }π    Delay(20);                                { wait for response   }π    Min := Port[j];                           { version minor part  }π  END {SBver};ππBEGINππ  SBver (Major, Minor);π  WriteLn;π  WriteLn ('Sound Blaster version: ',Major,'.',Minor);π  WriteLn;ππEND.π                                                                                                                      9      08-25-9409:12ALL                      DANIEL SANDS             Wav Player               SWAG9408    ½mPδ    62     ■"   {π>Does anybody know how to load and play a wav in pascal? And I still need toπ>know how to load mods. And I would like to know how to load any other soundπ>files that you know of other than pc speaker beeps. ThanksππI made a WAV player in Pascal, but the source is a few lines long.  <G>ππ Okay.  It will play 4-bit ADPCM wavs, but not well.  Need to get the SBπdeveloper's kit to figure out why.  Oh well.π}ππ{$M 16384,0,655360}ππuses Dos, CRT, objects;ππconst SBase = $220;               {Default port base for Sound Blaster.π                                   Change if necessary}π      SIrq  = 7;                  {Default Irq line for Sound Blaster.π                                   Change if necessary}π      SDMA  = 1;                  {Default DMA channel for Sound Blaster.}ππtypeπ TWAVRec = recordπ             ID: LongInt;π            Len: LongInt;π           end;π PWAVFmt = ^TWAVFmt;π TWAVFmt = recordπ            case word ofπ             1:( FTag: word;π                 NChan: word;π                 SampR: word;π                 AvgSR: word;π                 BLKAl: word;π                 FMTLen: word;π                 FMTDat: array[0..256] of byte);π             2:( Chunk:Pointer);π           end;πvarπ WAVFile: TDosStream;             {WAV file object}π BlkID: TWAVRec;                  {ID for each block in WAV}π BlkFmt: PWAVFmt;                 {Block format}π TotalSz: LongInt;                {Total size of WAV data}π DSPCmd: byte;π NumBits: byte;π SampByte: byte;π BlockSize: word;π EOB: boolean;π DF: String;ππprocedure NewBlock; interrupt;    {Procedure to set up next block or}πvar X:Byte;                       {end playback}πbeginππ X := port[SBase+$e];π port[$20] := $20;π EOB := true;ππend;ππprocedure PrepareSB;πbeginππ SetIntVec(SIrq + 8, @NewBlock);           {Set up service routine}ππ asmπ  in al,$61                                 {Enable timer 2, but}π  and al,$fc                                {do not turn on sound.}π  or al,1π  out $61,alππ  stiππ  mov dx,SBase+6                            {DSP (Digital Sound Processor)π                                             reset port}π  mov al,1                                  {Reset command}π  out dx,alππ  mov bx,4π  call @9                                   {Wait 4 clocks}ππ  mov al,0                                  {Normal mode}π  out dx,alππ @3: mov dx,SBase+$e                        {DSP status port}π @2: in al,dx                               {Read status}π  test al,$80                               {If high bit not set, no data}π  jz @2                                     {ready}ππ  mov dx,Sbase+$a                           {DSP read port}π  in al,dx                                  {Read status}π  cmp al,$aa                                {AA indicates ready}π  jnz @3π  jmp @4π @5:π  in al,dx                                  {Wait for response to last byte}π  test al,$80                               {sent}π  jnz @5π  mov al,ahπ  out dx,al                                 {Send next byte}π  retππ @9:π  push bxπ  mov al,$b6                                {Write count to timer #3}π  out $43,alππ  mov al,0                                  {Low byte of count}π  out $42,alππ  mov al,$10                                {High byte count}π  out $42,alππ  sub bx,$1000π  neg bx                                    {1000h-clocks=desired count}π @10:π  mov al,$80                                {Read count from timer}π  out $43,alππ  in  al,$42                                {Low byte}π  mov ah,alπ  in  al,$42                                {High byte}π  xchg ah,alππ  cmp bx,ax                                 {Pause until count reached}π  jl  @10π  pop bxπ  retπ @4:π  mov dx,SBase+$cππ  mov ah,$40                                {Set time constant}π  call @5ππ  mov ah,SampByte                           {Time divisor}π  call @5ππ end;ππ port[$21] := port[$21] and not (1 shl SIRQ);   {Enable SB interrupt}ππend;ππprocedure ErrorEnd;πbeginπ WAVFile.Done;π Writeln('Error in .WAV');π Halt(1);πend;ππprocedure PlaySound(SndLen: longint);ππvar AbsAddr: LongInt;π    FirstBlk, SecBlk, CurBlk: Pointer;ππbeginππ EOB := False;ππ GetMem(BlkFmt, BlockSize*2);π FirstBlk := BlkFmt;π SecBlk := pointer(longint(FirstBlk) + BlockSize);π CurBlk := FirstBlk;πππ WAVFile.Read(BlkFmt^, BlockSize);π SndLen := SndLen - BlockSize;ππ repeatπ  AbsAddr := Seg(CurBlk^);π  AbsAddr := AbsAddr * 16 +Ofs(CurBlk^);π  SndLen := SndLen - BlockSize;π  asmπ   jmp @4ππ  @5:π   in al,dx                                 {Wait for response to last byte}π   test al,$80                              {sent}π   jnz @5π   mov al,ahπ   out dx,al                                {Send next byte}π   retππ  @4:ππ   mov bx,1π   mov cx,integer(AbsAddr)π   mov dx,SBase+$cππ   mov al,0                                 {Clear byte high/low flip-flop}π   out $c,alππ   mov al,$49                               {Set memory read, single transfer,}π   out $b,al                                {channel 1}ππ   mov al,cl                                {Enter base address}π   out SDMA*2,alπ   mov al,chπ   out SDMA*2,alππ   mov ax,integer(AbsAddr+2)                {High 4 bits goes to DMA page reg}π   mov dx,$83π   mov cl,SDMAπ   sub cl,2π   mov ch,2                                 {Calculate DMA page address}π   shr ch,cl                                {87, 83, 81, 82 channel order}π   xor dl,chπ   out dx,al                                {Send page byte}ππ   mov ax,BlockSize                         {Set byte count}π   out SDMA*2+1,alπ   xchg al,ahπ   out SDMA*2+1,alπ   push axππ   mov al,SDMA                              {Re-enable DMA channel 1}π   out $a,alππ   mov dx,SBase+$c                          {DSP port}ππ   mov ah,DSPCmd                            {DMA 8-bit transfer}π   call @5ππ   pop ax                                   {Get transfer again}π   mov bl,alπ   call @5π   mov ah,blπ   call @5ππ  end;ππ  DSPCmd := DSPCmd and $fe;ππ  if (CurBlk = FirstBlk) then CurBlk := SecBlk else CurBlk := FirstBlk;π  if SndLen > 0 then WAVFile.Read(CurBlk^, BlockSize);ππ  while not EOB doπ   if Keypressed then ErrorEnd;π  EOB := False;ππ until (SndLen<=0);πend;πππbeginππ DF := ParamStr(1);ππ WAVFile.Init(DF, stOpenRead);              {Open WAV file}π WAVFile.Read(BlkID, SizeOf(TWAVRec));      {Read in first block}ππ if BlkID.ID = $46464952 then               {ID of WAV file}π beginπ  TotalSz := BlkID.Len;                     {Get total size}π  repeatπ   WAVFile.Read(BlkID, 4);                  {Read in type chunk}π   TotalSz := TotalSz - 4;                  {and update TS}ππ   if BlkID.ID <> $45564157 then ErrorEnd;  {Must be "WAVE"}π   repeatπ    WAVFile.Read(BlkID, SizeOf(TWAVRec));    {Read in format chunk}π    TotalSz := TotalSz - SizeOf(TWavRec);ππ    if BlkID.ID = $20746d66  then            {"fmt ", set WAV format}π    beginπ     getmem(BlkFmt, BlkID.Len);π     WAVFile.Read(BlkFmt^, BlkID.Len);π     TotalSz := TotalSz - BlkID.Len;π     with BlkFmt^ doπ     beginπ      if FTag = $200 then DSPCmd := $75 else {ADPCM 4-bit compression}π       if FTag = 1 then DSPCmd := $14 else   {Normal}π        ErrorEnd;π      if DSPCmd = $75 then NumBits := 4 else NumBits := 8;π      if NChan = 2 then DSPCmd := DSPCmd + 8; {Stereo}π      SampByte := 256-(1000000 div SampR);   {Sampling rate}π      BlockSize := BlkAl;                    {Size of buffer}π     end;π     freemem(BlkFmt, BlkID.Len);π    end elseππ    if BlkID.ID = $61746164 thenπ    beginπ     PrepareSB;                              {Perform init stuff}π     TotalSz := TotalSz - BlkID.Len;π     PlaySound(BlkID.Len);π    end elseππ     ErrorEnd;π   until TotalSz <= 0;π  until TotalSz <= 0;π end elseπ  ErrorEnd;π WAVFile.Done;π port[$21] := port[$21] or (1 shl SIrq);πend.π                                                                         10     08-26-9408:32ALL                      SWAG SUPPORT TEAM        Call AD-LIB sound driver SWAG9408    8#φv    76     ■"   unit MusicIO;π{Contains procedures and function to call to Ad-Lib sound Driver.π if Sound Driver is not Loaded the system WILL Crash.π Parameters must be passed backwards since the sound driver is madeπ for a C parameter passing sequence.}ππinterfaceππ  usesπ    DOS;ππ  typeπ    Instrument = array[1..26] of integer;ππ  varπ    GActVoice :word; {Active Voice}π    GT        :array[0..10] of Instrument; {use global variable to keep array valid}ππ  procedure InitDriver;π  procedure RelTimeStart(TimeNum,TimeDen :integer);π  procedure SetState(State :integer);π  function GetState :boolean;π  procedure SetMode(PercussionMode :integer);π  function SetVolume(VolNum,VolDen,TimeNum,TimeDen :integer) :boolean;π  function SetTempo(Tempo,TimeNum,TimeDen :integer) :boolean;π  procedure SetActVoice(Voice :word);π  function PlayNote(Pitch :integer; LengthNum,LengthDen :word) :boolean;π  function SetTimbre(TimeNum,TimeDen :word) :boolean;π  procedure SetTickBeat(TickBeat :integer);π  procedure DirectNoteOn(Voice :word; Pitch :integer);π  procedure DirectNoteOff(Voice :word);π  procedure DirectTimbre;π  procedure LoadInstrument(FileSpec :string);π  function LoadSong(FileSpec :string) :boolean;πππimplementationππ  {Returns True if file exists; otherwise, it returns False. Closes the file if it exists.}π  function Exist(fs :string) :boolean;π    varπ      f: file;π    beginπ      {$I-}π      Assign(f,fs);π      Reset(f);π      Close(f);π      {$I+}π      Exist:=(IOResult=0) and (fs<>'');π    end;πππ  procedure InitDriver;π    {Initialize Sound Driver}π    Varπ      r :registers; TmpP:Pointer;π    Beginπ      GetIntVec(101,TmpP);π      If TmpP = Nil Thenπ      Beginπ         WriteLn('Sound Driver Not Installed!');π         Halt(0);π      End;ππ      R.SI:=0;π      Intr(101,r);π    End;ππ  procedure RelTimeStart(TimeNum,TimeDen :integer);π    {Set Relative Time to Start}π    varπ      TD,TN :integer;π      r :registers;π    beginπ      TD:=TimeDen;π      TN:=TimeNum;ππ      r.SI:=2;π      r.ES:=Seg(TN);π      r.BX:=Ofs(TN);ππ      Intr(101,r);π    end;ππ  procedure SetState(State :integer);π    {Start or Stop a Song}π    varπ      r :registers;π    beginπ      r.SI:=3;π      r.ES:=Seg(State);π      r.BX:=Ofs(State);ππ      Intr(101,r);π    end;ππ  function GetState :boolean;π    varπ      r :registers;π    beginπ      r.SI:=4;π      r.ES:=Seg(GetState);π      r.BX:=Ofs(GetState);ππ      Intr(101,r);ππ      GetState:=(r.BP=1);π    end;ππ  procedure SetMode(PercussionMode :integer);π    {Percussion or Melodic Mode}π    varπ      r :registers;π    beginπ      r.SI:=6;π      r.ES:=Seg(PercussionMode);π      r.BX:=Ofs(PercussionMode);ππ      Intr(101,r);π    end;ππ  function SetVolume(VolNum,VolDen,TimeNum,TimeDen :integer) :boolean;π    varπ      TD,TN,VD,VN :word; {To put variables values in proper order in memory}π      r           :registers;π    beginπ      TD:=TimeDen;π      TN:=TimeNum;π      VD:=VolDen;π      VN:=VolNum;ππ      r.SI:=8;π      r.ES:=Seg(VN);π      r.BX:=Ofs(VN);ππ      Intr(101,r);ππ      SetVolume:=(r.BP=1);π    end;ππ  function SetTempo(Tempo,TimeNum,TimeDen :integer) :boolean;π    varπ      TD,TN,TP :integer; {To put variables values in proper order in memory}π      r        :registers;π    beginπ      TD:=TimeDen;π      TN:=TimeNum;π      TP:=Tempo;ππ      r.SI:=9;π      r.ES:=Seg(TP);π      r.BX:=Ofs(TP);ππ      Intr(101,r);ππ      SetTempo:=(r.BP=1);π    end;ππ  procedure SetActVoice(Voice :word);π    varπ      r :registers;π    beginπ      GActVoice:=Voice;ππ      r.SI:=12;π      r.ES:=Seg(Voice);π      r.BX:=Ofs(Voice);ππ      Intr(101,r);π    end;ππ  function PlayNoteDel(Pitch :integer; LengthNum,LengthDen,DelayNum,DelayDen :word) :boolean;π    varπ      DD,DN,LD,LN :word;π      P           :integer;π      r           :registers;π    beginπ      P:=Pitch;π      LD:=LengthDen;π      LN:=LengthNum;π      DN:=DelayNum;π      DD:=DelayDen;ππ      r.SI:=14;π      r.ES:=Seg(P);π      r.BX:=Ofs(P);ππ      Intr(101,r);ππ      PlayNoteDel:=(r.BP=1);π    end;ππ  function PlayNote(Pitch :integer; LengthNum,LengthDen :word) :boolean;π    varπ      LD,LN :word;π      P     :integer;π      r     :registers;π    beginπ      P:=Pitch;π      LD:=LengthDen;π      LN:=LengthNum;ππ      r.SI:=15;π      r.ES:=Seg(P);π      r.BX:=Ofs(P);ππ      Intr(101,r);ππ      PlayNote:=(r.BP=1);π    end;ππ  function SetTimbre(TimeNum,TimeDen :word) :boolean;π    varπ      TD,TN :word;π      T     :^integer;π      c1,c2 :byte;π      r     :registers;π    beginπ      T:=Addr(GT[GActVoice]);π      TN:=TimeNum;π      TD:=TimeDen;ππ      r.SI:=16;π      r.ES:=Seg(T);π      r.BX:=Ofs(T);ππ      Intr(101,r);ππ      SetTimbre:=(r.BP=1);π    end;ππ  function SetPitch(DeltaOctave,DeltaNum,DeltaDen :integer; TimeNum,TimeDen :word) :boolean;π    varπ      TD,TN   :word;π      DD,DN,D :integer;π      c1,c2   :byte;π      r       :registers;π    beginπ      D:=DeltaOctave;π      DN:=DeltaNum;π      DD:=DeltaDen;π      TN:=TimeNum;π      TD:=TimeDen;ππ      r.SI:=16;π      r.ES:=Seg(D);π      r.BX:=Ofs(D);ππ      Intr(101,r);ππ      SetPitch:=(r.BP=1);π    end;ππ  procedure SetTickBeat(TickBeat :integer);π    varπ      r :registers;π    beginπ      r.SI:=18;π      r.ES:=Seg(TickBeat);π      r.BX:=Ofs(TickBeat);ππ      Intr(101,r);π    end;ππ  procedure DirectNoteOn(Voice :word; Pitch :integer);π    varπ      P :integer;π      V :word;π      r :registers;π    beginπ      P:=Pitch;π      V:=Voice;ππ      r.SI:=19;π      r.ES:=Seg(V);π      r.BX:=Ofs(V);ππ      Intr(101,r);π    end;ππ  procedure DirectNoteOff(Voice :word);π    varπ      r :registers;π    beginπ      r.SI:=20;π      r.ES:=Seg(Voice);π      r.BX:=Ofs(Voice);ππ      Intr(101,r);π    end;ππ  procedure DirectTimbre;π    varπ      T     :^integer;π      V     :word;π      r     :registers;π    beginπ      V:=GActVoice;π      T:=Addr(GT[V]);ππ      r.SI:=21;π      r.ES:=Seg(V);π      r.BX:=Ofs(V);ππ      Intr(101,r);π    end;ππ  procedure LoadInstrument(FileSpec :string);π    {Load an Instument from Disk and Place in Array}π    varπ      c1 :byte;π      n  :integer;π      f  :file of integer;π    beginπ      if not(Exist(FileSpec)) then FileSpec:='C:\MUSIC\PIANO1.INS';π      Assign(f,FileSpec);π      Reset(f);π      Read(f,n);π      for c1:=1 to 26 doπ        Read(f,GT[GActVoice,c1]);π      Close(f);π    end;ππ  function LoadSong;π    {Read a .ROL file and place song in Buffer}π    varπ      nb :byte;π      ns :string[255];π      ni,ni2,ni3,ni4,BPM :integer;π      c1,c2  :word;π      nr,nr2 :real;π      fl :boolean;π      f  :file;π    procedure StringRead(len :word); {uses f,ns}π      varπ        nc :char;π        c1 :word;π      beginπ        ns:='';π        for c1:=1 to len doπ          beginπ            BlockRead(f,nc,1);π            ns:=ConCat(ns,nc);π          end;π      end;π    procedure TempoRead; {uses f,nb}π      varπ        b1,b2,b3,b4 :byte;π      beginπ        BlockRead(f,b1,1);π        BlockRead(f,b2,1);π        BlockRead(f,b3,1);π        BlockRead(f,b4,1);π        nb:=(b3{ div 2});π      end;π    procedure VolumeRead;π      varπ        b1,b2,b3,b4 :byte;π      beginπ        BlockRead(f,b1,1);π        BlockRead(f,b2,1);π        BlockRead(f,b3,1);π        BlockRead(f,b4,1);π        nb:=51+Round(b3/2.5);π      end;π    beginπ      LoadSong:=true;π      if not(Exist(FileSpec))π        then beginπ               LoadSong:=false;π               Exit;π             end;ππ      InitDriver;π      RelTimeStart(0,1);π      Assign(f,FileSpec);π      Reset(f,1);π      StringRead(44);π      BlockRead(f,ni,2); SetTickBeat(ni); {Ticks per Beat}π      BlockRead(f,ni,2); BPM:=ni; {Beats per Measure}π      StringRead(5);π      BlockRead(f,nb,1); SetMode(1); {Mode}π      StringRead(143);π      TempoRead; fl:=SetTempo(nb,0,1); {Tempo}π      BlockRead(f,ni,2);π      for c1:=1 to ni doπ        beginπ          BlockRead(f,ni2,2);π          TempoRead; fl:=SetTempo(nb,ni2,1); {Tempo}π        end;π      for c1:=0 to 10 do {11 Voices}π        beginπ          SetActVoice(c1);π          StringRead(15);π          BlockRead(f,ni2,2); {Time in ticks of last Note}π          c2:=0;π          while (c2<ni2) doπ            beginπ              BlockRead(f,ni3,2); {Note Pitch}π              BlockRead(f,ni4,2); {Note Duration}π              fl:=PlayNote(ni3-60,ni4,BPM); {Note}π              c2:=c2+ni4; {Summation of Durations}π            end;π          StringRead(15);π          BlockRead(f,ni2,2);π          for c2:=1 to ni2 do {Instuments}π            beginπ              BlockRead(f,ni3,2);π              StringRead(9);π              nb:=Pos(#0,ns);π              Delete(ns,nb,Length(ns));π              LoadInstrument(ConCat('C:\MUSIC\',ns,'.INS'));π              fl:=SetTimbre(ni3,1);π              StringRead(1);π              BlockRead(f,ni4,2);π            end;π          StringRead(15);π          BlockRead(f,ni2,2);π          nb:=1;π          for c2:=1 to ni2 do {Volume}π            beginπ              BlockRead(f,ni3,2);π              fl:=SetVolume(100,nb,ni3,1); {Use inverse to disable Relative}π              VolumeRead;π              fl:=SetVolume(nb,100,ni3,1);π            end;π          StringRead(15);π          BlockRead(f,ni2,2);π          for c2:=1 to ni2 do {Pitch -disabled}π            beginπ              BlockRead(f,ni3,2);π              BlockRead(f,nr,4);π              if (nr=0) then nr2:=1 else nr2:=nr;π{             fl:=SetPitch(0,Abs(Trunc(nr*100)),Trunc((nr/nr2)*100),ni3,1);}π            end;π        end;π      Close(f);π    end;ππend.π